package studio.greeks.codes.region.tree;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import studio.greeks.codes.region.Region;

import java.io.InputStream;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 *
 * @author dfs
 * @description studio.greeks.codes.region.tree normal-codes
 * @date 2021/5/7 01:15
 */
@Data
public class RegionTree {
    private static final int MAX_LEVEL = 4;
    private static RegionTree defaultTree;
    private Map<String, RegionNode> regionNodeMap;
    private Map<Integer, List<RegionNode>> lineMap;
    private RegionNode root;

    /**
     * 一颗默认的地区树
     * @return 地区树
     */
    public static RegionTree defaultTree(){
        if (defaultTree == null) {
            synchronized (RegionTree.class) {
                if (defaultTree == null) {
                    defaultTree = new RegionTree();
                    try (InputStream is = RegionTree.class.getResourceAsStream("/china-all.json");) {
                        List<Region> list = new ObjectMapper().readerForListOf(Region.class).readValue(is);
                        defaultTree.regionNodeMap = list.stream().parallel()
                                .filter(region -> region.getLevel() <= MAX_LEVEL)
                                .map(region -> {
                            RegionNode node = new RegionNode();
                            node.setRegion(region);
                            return node;
                        }).collect(Collectors.toMap(node -> node.getRegion().getSiteId(), Function.identity()));

                        defaultTree.lineMap = defaultTree.regionNodeMap.values().stream().parallel()
                                .collect(Collectors.groupingBy(node -> node.getRegion().getLevel()));

                        defaultTree.lineMap.values().stream().flatMap(Collection::stream)
                                .forEach(node -> {
                                            String pid = node.getRegion().getPid();
                                            RegionNode parent = defaultTree().regionNodeMap.get(pid);
                                            if (parent != null) {
                                                node.setParent(parent);
                                                List<RegionNode> children = parent.getChildren() == null ? new LinkedList<>() : parent.getChildren();
                                                children.add(node);
                                                parent.setChildren(children);
                                            }
                                        }
                                    );

                        defaultTree.root = defaultTree.regionNodeMap.values().stream().filter(RegionNode::isRoot)
                                .findFirst().orElseThrow(() -> new RuntimeException("root节点生成失败"));
                    } catch (Exception e) {
                        throw new RuntimeException("未加载到'china-all.json'", e);
                    }
                }
            }
        }
        return defaultTree;
    }
}
